package de.hijacksoft.isle.adapters;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import de.hijacksoft.isle.classes.Item;
import de.hijacksoft.isle.classes.Price;
import de.hijacksoft.isle.R;
import de.hijacksoft.isle.classes.Variables;

public class MainExpandableListAdapter extends BaseExpandableListAdapter {

    // Constants
    private static final String TAG = "ExpandableListAdapter";
    // option numbers for the modes
    public static final int CATEGORY_ID = -1;
    public static final int CHECKBOX = 1;
    public static final int PRICE = 2;
    public static final int ICONS = 3;
    public static final int CATEGORIES = 4;
    public static final int BARCODE = 5;
    // used to inflate the layout
    private int layoutResourceId;
    // settings
    private boolean setting_checkbox, setting_price, setting_icons, setting_categories = true;
    private boolean setting_barcode = false;
    // Variables
    private Context context;
    private ArrayList<String> groups;
    private ArrayList<ArrayList<Item>> children;
    private DBAdapter adapter;

    /**
     * Sets the display mode of the list
     * @param mode the mode to be used
     * @param value enable (true) or disable (false) mode
     */
    public void setMode(int mode, boolean value) {
        switch (mode) {
            case CHECKBOX:
                setting_checkbox = value;
                break;
            case PRICE:
                setting_price = value;
                break;
            case ICONS:
                setting_icons = value;
                break;
            case CATEGORIES:
                setting_categories = value;
                break;
            case BARCODE:
                setting_barcode = value;
                break;
        }
    }

    @Override
    public boolean areAllItemsEnabled() {
        return true;
    }

    /**
     * @param context an activity context
     * @param layoutResourceId a layout containing all the views used
     * @param children the array containing the items to manage
     * @param adapter a database adapter
     */
    public MainExpandableListAdapter(Context context, int layoutResourceId, ArrayList<Item> children, DBAdapter adapter) {
        this.context = context;
        this.groups = new ArrayList<String>();
        this.children = new ArrayList<ArrayList<Item>>();
        this.layoutResourceId = layoutResourceId;
        this.adapter = adapter;

        // add all items from the list
        if (children != null) {
            for (Item item : children) {
                addItem(item);
            }
        }

    }

    public void addItem(Item item) {

        Log.v(TAG, "Adding item: " + item.name + ", " + item.category);
        String category = item.category.name;
        if (!groups.contains(category)) {
            groups.add(category);
        }
        int index = groups.indexOf(category);
        if (children.size() < index + 1) {
            children.add(new ArrayList<Item>());
        }
        children.get(index).add(item);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return children.get(groupPosition).get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

        final Item item = (Item) getChild(groupPosition, childPosition);

        if (convertView == null) {
            LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflator.inflate(layoutResourceId, null);
        }

        // get the Views
        ImageView barcode = (ImageView) convertView.findViewById(R.id.item_barcode_icon);
        ImageView photo = (ImageView) convertView.findViewById(R.id.item_photo);
        final CheckBox checkbox = (CheckBox) convertView.findViewById(R.id.item_checkbox);
        TextView name = (TextView) convertView.findViewById(R.id.item_name);
        TextView amount = (TextView) convertView.findViewById(R.id.item_amount);
        TextView price = (TextView) convertView.findViewById(R.id.item_price);
        ImageView category = (ImageView) convertView.findViewById(R.id.item_category);

        // set the category color
        if (!PreferenceManager.getDefaultSharedPreferences(context).getBoolean(Variables.PREFERENCE_SHOWCATEGORY, false)) {
            category.setVisibility(View.GONE);
        } else {
            category.setBackgroundColor(item.category.color);
        }

        // enable/disable price text
        if (!this.setting_price) {
            price.setVisibility(View.GONE);
        } else {
            price.setVisibility(View.VISIBLE);
        }

        // enable/disable barcode icon
        if (!this.setting_barcode) {
            barcode.setVisibility(View.GONE);
        } else {
            if (item.barcode == 0) {
                barcode.setVisibility(View.GONE);
            } else {
                barcode.setVisibility(View.VISIBLE);
            }
        }

        price.setText(new Price(context, item.price).toString());
        name.setText(item.name);

        // enable/disable checkbox and check if all items are checked on each click
        if (!this.setting_checkbox) {
            checkbox.setVisibility(View.GONE);
        } else {

            checkbox.setVisibility(View.VISIBLE);

            checkbox.setChecked(item.bought);
            Log.i(TAG, "bought " + item.name + ": " + item.bought);

            checkbox.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    item.bought = checkbox.isChecked();
                    adapter.onItemBought(item);
                    if (allChecked()) {
                        onAllChecked();
                    }
                }
            });

        }

        // enable/disable item icon (depending on preferences and settings)
        if (!PreferenceManager.getDefaultSharedPreferences(context).getBoolean(Variables.PREFERENCE_SHOWICONS, true) || !setting_icons) {
            Log.d(TAG, "setting icon visibility to gone");
            photo.setVisibility(View.GONE);
        } else {

            photo.setVisibility(View.VISIBLE);

            try {
                Log.d(TAG, item.name + ": " + item.image.toString());
                photo.setImageBitmap(readBitmap(item.image));
            } catch (Exception e) {
                Log.d(TAG, "Error reading bitmap: " + e.toString());
                photo.setImageDrawable(context.getResources().getDrawable(R.drawable.noicon));
            }

        }

        String unit = "?";
        switch (item.unit) {
            case 'k':
                unit = context.getString(R.string.unit_kg);
                break;
            case 'l':
                unit = context.getString(R.string.unit_l);
                break;
            case 'm':
                unit = context.getString(R.string.unit_ml);
                break;
            case 'g':
                unit = context.getString(R.string.unit_g);
                break;
            case 'p':
                unit = context.getString(R.string.unit_pc);
                break;
        }

        amount.setText((Math.rint(item.amount * 100) / 100) + " " + unit);

        int id = 0;
        for (int i = 0; i < groupPosition; i++) {
            id += children.get(i).size();
        }

        convertView.setId(id + childPosition);

        return convertView;

    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return children.get(groupPosition).size();
    }

    public int getChildrenCount() {
        int sum = 0;
        for (ArrayList<Item> sublist : children) {
            for (Item item : sublist) {
                sum++;
            }
        }
        return sum;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groups.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return groups.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    public boolean allChecked() {

        for (ArrayList<Item> sublist : children) {
            for (Item item : sublist) {
                if (!item.bought) {
                    return false;
                }
            }
        }
        return true;

    }

    public void onAllChecked() {
        // This method wants to be overridden <3
    }

    public void onDataSetChange() {
        // This method wants to be overridden <3
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
        onDataSetChange();
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

        String group = (String) getGroup(groupPosition);

        if (group.equals("")) {
            group = context.getString(R.string.uncategorized);
        }

        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.listcategory, null);
        }

        // set the text of a category
        TextView tv = (TextView) convertView.findViewById(R.id.listcategory_textview_name);
        tv.setText(group);

        convertView.setId(CATEGORY_ID);

        return convertView;

    }

    /**
     * @author Lumis (StackOverflow)
     * @param selectedImage An Uri to an image
     * @return returns the image as a Bitmap object
     */
    private Bitmap readBitmap(Uri selectedImage) {
        Bitmap bm = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2; //reduce quality 
        AssetFileDescriptor fileDescriptor = null;
        try {
            fileDescriptor = context.getContentResolver().openAssetFileDescriptor(selectedImage, "r");
        } catch (FileNotFoundException e) {
            // e.printStackTrace(); // modified by HiJack Soft for Android
            Log.d(TAG, "Error reading a bitmap: " + e.getMessage());
        } finally {
            try {
                bm = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, options);
                fileDescriptor.close();
            } catch (IOException e) {
                // e.printStackTrace(); // modified by HiJack Soft for Android
                Log.d(TAG, "Error reading a bitmap: " + e.getMessage());
            }
        }
        return bm;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int arg0, int arg1) {
        return true;
    }

    public boolean remove(Item item) {
        for (ArrayList<Item> items : children) {
            for (Item i : items) {
                if (i.id == item.id) {
                    items.remove(i);
                    return !items.isEmpty();
                }
            }
        }
        return false;
    }
}
